﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bookkeeping.Core.Entities;

namespace Bookkeeping.Core.Services
{
    public class Budget
    {
        public Budget(IEnumerable<Post> posts)
        {
            Posts = posts;
        }

        public IEnumerable<Post> Posts { get; private set; }

        public IEnumerable<Post> Savings
        {
            get
            {
                return GetPostsByType(PostType.Saving);
            }
        }

        public IEnumerable<Post> Incomes
        {
            get
            {
                return GetPostsByType(PostType.Income);
            }
        }
        
        public IEnumerable<Post> Expenses
        {
            get
            {
                return GetPostsByType(PostType.Expense);
            }
        }
        
        public double TotalExcludingSavings
        {
            get
            {
                double totalIncome = CalculateTotal(Incomes);
                double totalExpense = CalculateTotal(Expenses);

                // The expense sum is negative, hence add the two totals
                return totalIncome + totalExpense;
            }
        }

        public double TotalIncludingSavings
        {
            get
            {
                double totalIncome = CalculateTotal(Incomes);
                double totalExpense = CalculateTotal(Expenses);
                double totalSavings = CalculateTotal(Savings);

                // The expense sum is negative, hence add the expenses to the incomes.
                // However, the savings are positive so subtract the savings from the total
                return totalIncome + totalExpense - totalSavings;
            }
        }

        public double TotalExpenses
        {
            get
            {
                return CalculateTotal(Expenses);
            }
        }

        public double TotalIncomes
        {
            get
            {
                return CalculateTotal(Incomes);
            }
        }

        public double TotalSavings
        {
            get
            {
                return CalculateTotal(Savings);
            }
        }

        private static double CalculateTotal(IEnumerable<Post> posts)
        {
            return posts.Aggregate(0.0, (total, post) => total + post.Amount);
        }

        private IEnumerable<Post> GetPostsByType(PostType postType)
        {
            return Posts.Where(p => p.Type == postType);
        }
    }
}
